package com.mars.security.browser;

import com.mars.security.core.authentication.AbstractChannelSecurityConfig;
import com.mars.security.core.authentication.mobile.SmsCodeAuthenticationSecurityConfig;
import com.mars.security.core.properties.SecurityConstants;
import com.mars.security.core.properties.SecurityProperties;
import com.mars.security.core.validate.code.ValidateCodeFilter;
import com.mars.security.core.validate.code.ValidateCodeSecurityConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.social.security.SpringSocialConfigurer;

import javax.sql.DataSource;

/**
 * 安全配置类：
 * 配置SpringSecurity：
 * 1、继承 WebSecurityConfigurerAdapter,web应用安全配置的适配器
 * 2、添加 @Configuration 注册为配置类
 * 3、覆盖configure(HttpSecurity http)方法
 *
 *
 * @author MARS
 * @date 2018/7/19
 */

@Configuration
public class BrowserSecurityConfig extends AbstractChannelSecurityConfig {

    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;

    /**
     *    记住我 认证成功后，需调用UserDetailService
     */
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;

    @Autowired
    private ValidateCodeSecurityConfig validateCodeSecurityConfig;

    @Autowired
    private SpringSocialConfigurer imoocSocialSecurityConfig;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 验证码过滤器
        ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
        // 自定义的错误处理其设置到自定义的过滤器中
        //validateCodeFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
        // 自定义的properties配置
        //validateCodeFilter.setSecurityProperties(securityProperties);
        //validateCodeFilter.afterPropertiesSet();

        // 短信验证码配置
        //SmsCodeFilter smsCodeFilter = new SmsCodeFilter();
        //smsCodeFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
        //smsCodeFilter.setSecurityProperties(securityProperties);
        //smsCodeFilter.afterPropertiesSet();

        // 表单设置（抽取）
        applyPasswordAuthenticationConfig(http);

        http.apply(smsCodeAuthenticationSecurityConfig) // 添加短信验证码过滤器
                .and()
            .apply(validateCodeSecurityConfig) // 添加自定义的过滤器，放置在 UsernamePasswordAuthenticationFilter 之前使用
                .and()
            .apply(imoocSocialSecurityConfig) // 添加social过滤器
                .and()
            //.addFilterBefore(smsCodeFilter,UsernamePasswordAuthenticationFilter.class)
            // 添加自定义的过滤器，放置在 UsernamePasswordAuthenticationFilter 之前使用
            //.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
            // 表单登陆
            //.formLogin()
            //     // 个性化登陆页面配置
            //    .loginPage("/authentication/require")
            //     // 配置自定义处理登录url
            //    .loginProcessingUrl("/authentication/form")
            //    // 自定义配置成功登录后的处理
            //    .successHandler(myAuthenticationSuccessHandler)
            //    // 自定义配置登陆失败后的处理
            //    .failureHandler(myAuthenticationFailureHandler)
            //    .and()
            // 记住我
            .rememberMe()
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
                .userDetailsService(userDetailsService)
                .and()
            .authorizeRequests() // 开启请求做授权
            //.antMatchers("/authentication/require").permitAll() // 访问这个路径的使用不需要权限认证
            //访问这个路径的使用不需要权限认证
                .antMatchers(
                        SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
                        SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE,
                        securityProperties.getBrowser().getLoginPage(),
                        SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX+"/*"
                        //securityProperties.getBrowser().getSignUpUrl(),
                        //"/user/regist"
                ).permitAll()
                // 对于任何请求
                .anyRequest()
                // 都需要做认证
                .authenticated()
                .and()
             // 跨站请求伪造防护功能关闭
            .csrf().disable()
            //.and()
            //.apply(imoocSocialSecurityConfig)
        ;
    }


    /**
     * 配置 记住我：
     * 1、引入 TokenRepository，JdbcTokenRepositoryImpl
     * 2、引入数据源
     */
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        // 指定数据源
        tokenRepository.setDataSource(dataSource);
        //tokenRepository.setCreateTableOnStartup(true); //启动的时候自动创建表
        return tokenRepository;
    }

}


